<?php

require_once( 'mvc/mvc-exception.php' );

require_once( 'flexical/admin/controller.php' );
require_once( 'flexical/admin/feed-cud-request.php' );
require_once( 'flexical/admin/feed-response.php' );
require_once( 'flexical/admin/feed-cud-response.php' );
require_once( 'flexical/admin/cud-request.php' );
require_once( 'flexical/admin/message.php' );

class Flexical_Admin_Feed_Controller extends Flexical_Admin_Controller
{
	public function respond( $request )
	{
		$response = null;

		if ( $request instanceof Flexical_Admin_Feed_CUD_Request )
		{
			if ( $request->cancel_selected )
			{
				$response = $this->show_feeds();
				$response->canceled = true;
			}

			else
			{
				switch ( $request->operation )
				{
					case Flexical_Admin_CUD_Request::$CREATE:
						$response = $this->create( $request );
						break;

					case Flexical_Admin_CUD_Request::$UPDATE:
						$response = $this->update( $request );
						break;

					case Flexical_Admin_CUD_Request::$DELETE:
						$response = $this->delete( $request );
						break;

					default:
						throw new MVC_Exception( 'Unrecognized feed request CUD operation: ' . $request->operation );
						break;
				}
			}
		}

		else if ( $request instanceof Flexical_Admin_Show_Feeds_Request )
		{
			$response = $this->show_feeds();
			$response->canceled = $request->cancel_selected;
		}

		else if ( $request instanceof Flexical_Admin_Delete_All_Feeds_Request )
		{
			$response = $this->delete_all_feeds( $request );
		}

		else if ( $request instanceof Flexical_Admin_Import_Feeds_Request )
		{
			$response = $this->import_feeds( $request );
		}

		else if ( $request instanceof Flexical_Admin_Confirm_Delete_Feed_Request )
		{
			$response = $this->confirm_delete_feed( $request );
		}

		else if ( $request instanceof Flexical_Admin_Edit_Feed_Request )
		{
			$response = $this->edit_feed( $request );
		}

		else if ( $request instanceof Flexical_Admin_Test_Feed_Request )
		{
			$response = $this->test_feed( $request->feed );
		}

		else if ( $request instanceof Flexical_Admin_Test_All_Feeds_Request )
		{
			$response = $this->test_all_feeds();
		}

		else
		{
			throw new MVC_Exception( 'Unknown request type: ' . get_class( $this->request ) );
		}

		return $response;
	}

	private function create( $request )
	{
		$dao = $this->get_dao();

		$feed = $dao->create_feed( $request->object );

		$response = new Flexical_Admin_Feed_CUD_Response();
		$response->operation = Flexical_Admin_CUD_Response::$CREATE;
		$response->object = $feed;
		$response->feeds = $dao->read_feeds();

		return $response;
	}

	private function update( $request )
	{
		$dao = $this->get_dao();

		$dao->update_feed( $request->object );

		$response = new Flexical_Admin_Feed_CUD_Response();

		$response->operation = Flexical_Admin_CUD_Response::$UPDATE;
		$response->object = $dao->read_feed( $request->object->id );
		$response->feeds = $this->get_dao()->read_feeds();

		return $response;
	}

	private function delete( $request )
	{
		$dao = $this->get_dao();

		$feed = $dao->read_feed( $request->object->id );
		$dao->delete_feed( $feed->id );

		$response = new Flexical_Admin_Feed_CUD_Response();
		$response->operation = Flexical_Admin_CUD_Response::$DELETE;
		$response->object = $feed;
		$response->feeds = $dao->read_feeds();

		return $response;
	}

	private function get_listings_using_feed( $feed_id )
	{
		$listings = array();

		foreach ( $this->get_dao()->read_feed_queries() as $id => $feed_query )
		{
			if ( $feed_query->feed_id == $feed_id )
			{
				$listings[] = $this->get_dao()->read_listing( $feed_query->listing_id );
			}
		}

		return $listings;
	}

	private function show_feeds()
	{
		$response = new Flexical_Admin_Show_Feeds_Response();

		$response->feeds = $this->get_dao()->read_feeds();

		return $response;
	}

	private function delete_all_feeds( $request )
	{
		$response = null;
		$dao = $this->get_dao();

		$listings_using_feeds = $this->get_all_listings_using_feeds();

		if ( sizeof( $listings_using_feeds ) > 0 )
		{
			$response = new Flexical_Admin_Cant_Delete_Feeds_In_Use_Response( $listings_using_feeds );
		}

		else if ( $request->confirmed )
		{
			$feeds = $dao->read_feeds();

			foreach ( $feeds as $id => $feed )
			{
				$dao->delete_feed( $id );
			}

			$response = new Flexical_Admin_All_Feeds_Deleted_Response();
		}

		else
		{
			$response = new Flexical_Admin_Delete_All_Feeds_Not_Confirmed_Response();
		}

		$response->feeds = $dao->read_feeds();

		return $response;
	}

	private function get_all_listings_using_feeds()
	{
		$listings = array();
		$feed_queries = $this->get_dao()->read_feed_queries();

		foreach ( $this->get_dao()->read_feeds() as $feed_id => $feed )
		{
			foreach ( $feed_queries as $fq_id => $feed_query )
			{
				if ( $feed_query->feed_id == $feed_id )
				{
					$listings[ $feed_query->listing_id ] = $this->get_dao()->read_listing( $feed_query->listing_id );
				}
			}
		}

		return $listings;
	}

	private function import_feeds( $request )
	{
		$response = null;
		$dao = $this->get_dao();

		if ( $request->confirmed )
		{
			try
			{	
				$this->perform_feed_import( $request );
				$response = new Flexical_Admin_Feed_Import_Succeeded_Response();
			}

			catch ( Exception $e )
			{
				$response = new Flexical_Admin_Feed_Import_Failed_Response();
				$response->reason = $e->getMessage();
			}
		}

		else
		{
			$response = new Flexical_Admin_Feed_Import_Failed_Response();
			$response->reason = 'Confirmation check box is not checked';
		}

		$response->feeds = $dao->read_feeds();

		return $response;
	}

	private function perform_feed_import( $request )
	{
		$feeds = $this->get_cao()->read_feeds( $request->username, $request->password );

		switch ( $request->mode )
		{
			case 'append':
				$this->append_feeds( $feeds );
				break;

			case 'overwrite':
				$this->merge_feeds( $feeds );
				break;

			default:
				throw new Exception( "Unrecognized mode: " . $request->mode );
		}
	}

	private function append_feeds( $feeds = array() )
	{
		$dao = $this->get_dao();

		foreach ( $feeds as $feed )
		{
			if ( $dao->create_feed( $feed ) == null )
			{
				throw new Exception( "Error while adding feed to the database" );
			}
		}
	}

	private function merge_feeds( $feeds = array() )
	{
		$dao = $this->get_dao();
		$current_feeds = $dao->read_feeds();
		$feeds_by_url = array();

		foreach ( $current_feeds as $id => $feed )
		{
			$feeds_by_url[ $feed->url ] = $feed;
		}

		foreach ( $feeds as $feed )
		{
			if ( array_key_exists( $feed->url, $feeds_by_url ) )
			{
				$feed->id = $feeds_by_url[ $feed->url ]->id;
				$dao->update_feed( $feed );
			}

			else
			{
				$dao->create_feed( $feed );
			}
		}
	}

	private function confirm_delete_feed( $request )
	{
		$response = null;
		$dao = $this->get_dao();
		$feed = $dao->read_feed( $request->feed->id );
		$listings_using_feed = $this->get_listings_using_feed( $feed->id );

		if ( $feed == null )
		{
			$response = new Flexical_Admin_No_Such_Feed_Response();
			$response->object = $request->object;
			$response->feeds = $dao->read_feeds();
		}
		
		else if ( sizeof( $listings_using_feed ) > 0 )
		{
			$response = new Flexical_Admin_Cant_Delete_Feed_In_Use_Response( $feed, $listings_using_feed, $dao->read_feeds() );
		}

		else
		{
			$response = new Flexical_Admin_Confirm_Delete_Feed_Response( $feed );
		}

		return $response;
	}

	private function edit_feed( $request )
	{
		$response = null;
		$dao = $this->get_dao();
		$feed = $dao->read_feed( $request->feed->id );

		if ( $feed == null )
		{
			$response = new Flexical_Admin_No_Such_Feed_Response();
			$response->object = $request->object;
			$response->feeds = $dao->read_feeds();
		}

		else
		{
			$response = new Flexical_Admin_Edit_Feed_Response( $feed );
		}

		return $response;
	}

	private function test_all_feeds()
	{
		$response = new Flexical_Admin_Show_Feeds_Response();
		$feeds = $this->get_dao()->read_feeds();
		$cao = $this->get_cao();

		foreach ( $feeds as $id => $feed )
		{
			$feed->status = $cao->test_feed( $feed ) ? 'good' : 'bad';
		}

		$response->feeds = $feeds;

		return $response;
	}

	private function test_feed( $feed = null )
	{
		$response = null;

		$feeds = $this->get_dao()->read_feeds();

		if ( ! array_key_exists( $feed->id, $feeds ) )
		{
			$response = new Flexical_Admin_No_Such_Feed_Response();
			$response->object = $feed;
		}

		else
		{
			$feeds[ $feed->id ]->status = $this->get_cao()->test_feed( $feeds[ $feed->id ] ) ? 'good' : 'bad';

			$response = new Flexical_Admin_Show_Feeds_Response();
			$response->feeds = $feeds;
		}

		return $response;
	}

	private function get_cao()
	{
		require_once( 'flexical/service/cao-factory.php' );
		$factory = new Flexical_Service_CAO_Factory();
		return $factory->get_cao();
	}
}

?>
